using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace Extensions.Configuration.Database
{
    public static class DatabaseConfigurationExtensions
    {
        /// <summary>
        /// 添加数据库配置
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="databaseOptions">ef core数据库配置</param>
        /// <returns></returns>
        public static IConfigurationBuilder AddDatabase(this IConfigurationBuilder builder,
            Action<DbContextOptionsBuilder> databaseOptions) => builder.AddDatabase(databaseOptions, false);

        /// <summary>
        /// 添加数据库配置
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="databaseOptions">ef core数据库配置</param>
        /// <param name="reloadOnChange">是否更新后重新加载</param>
        /// <returns></returns>
        public static IConfigurationBuilder AddDatabase(this IConfigurationBuilder builder,
            Action<DbContextOptionsBuilder> databaseOptions, bool reloadOnChange) =>
            builder.AddDatabase(databaseOptions, default, reloadOnChange);

        /// <summary>
        /// 添加数据库配置
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="databaseOptions">ef core数据库配置</param>
        /// <param name="provider">数据库供应者</param>
        /// <param name="reloadOnChange">是否更新后重新加载</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static IConfigurationBuilder AddDatabase(this IConfigurationBuilder builder,
            Action<DbContextOptionsBuilder> databaseOptions, IDatabaseProvider provider, bool reloadOnChange)
        {
            if (builder == default)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            if (databaseOptions == default)
            {
                throw new ArgumentNullException(nameof(databaseOptions));
            }

            return builder.AddDatabase(source =>
            {
                source.DatabaseProvider = provider;
                source.DatabaseOptions = databaseOptions;
                source.ReloadOnChange = reloadOnChange;
            });
        }

        /// <summary>
        /// 添加数据库配置
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="configureSource">数据库配置源</param>
        /// <returns></returns>
        public static IConfigurationBuilder AddDatabase(this IConfigurationBuilder builder,
            Action<DatabaseConfigurationSource> configureSource)
        {
            return builder.Add(configureSource);
        }

        #region Other Extensions

        /// <summary>
        /// 获取默认的数据库提供者
        /// (官方库应该是先注入,再获取)
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static IDatabaseProvider GetDefaultDatabaseProvider(this IConfigurationBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            return new DefaultDatabaseProvider();
            // return builder.Properties.TryGetValue(FileConfigurationExtensions.FileProviderKey, out var obj)
            //     ? obj as IFileProvider
            //     : (IFileProvider)new PhysicalFileProvider(AppContext.BaseDirectory ?? string.Empty);
        }

        /// <summary>
        /// 获取数据库加载异常处理者
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static Action<DatabaseLoadExceptionContext> GetDatabaseLoadExceptionHandler(
            this IConfigurationBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            //TODO:需要更改
            return default;

            // return builder.Properties.TryGetValue(FileConfigurationExtensions.FileLoadExceptionHandlerKey, out var obj)
            //     ? obj as Action<FileLoadExceptionContext>
            //     : (Action<FileLoadExceptionContext>)null;
        }

        #endregion
    }
}